package cn.woblog.android.downloader;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.widget.Toast;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import cn.woblog.android.downloader.bean.DownloadInfo;
import cn.woblog.android.downloader.bean.DownloadStatus;
import cn.woblog.android.downloader.callback.OnDownloadListener;
import cn.woblog.android.common.db.DBController;
import cn.woblog.android.downloader.service.DownloadService;
import cn.woblog.android.common.utils.Const;
import cn.woblog.android.common.utils.Logs;
import cn.woblog.android.common.utils.NetworkUtils;


@SuppressLint("HandlerLeak")
public class DownloadManager implements OnDownloadListener {
	private static final String KEY_SHAREDPREFERENCE_NAME = "configure";
	private Context context;
	private static final int MIN_EXECUTE_INTERVAL = 500;
	protected static final int MSG_UPDATE_PROGRESS = 0;
	private static final int MSG_NEXT_DOWNLOAD_TASK = 1;
	private static final String TAG = "DownloadManager";
	protected static final int MSG_NEXT_DOWNLOAD_REMOVE_DATA = 2;
	protected static final int MSG_PAUSE_ALL = 3;
	public static final String KEY_USE_IN_3G = "KEY_USE_IN_3G";

	private DBController db;
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case MSG_UPDATE_PROGRESS:
				((DownloadInfo) msg.obj).getCallback().onLoading();
				break;
			case MSG_NEXT_DOWNLOAD_TASK:
				resumeInner((DownloadInfo) msg.obj);
				break;
			case MSG_NEXT_DOWNLOAD_REMOVE_DATA:
				removeInner((DownloadInfo) msg.obj);
				break;
			case MSG_PAUSE_ALL:
				pauseAll();
				break;

			default:
				break;
			}
		};
	};

	public class NetworkReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
//			State wifiState = null;
//			State mobileState = null;
//			ConnectivityManager cm = (ConnectivityManager) context
//					.getSystemService(Context.CONNECTIVITY_SERVICE);
//			if (cm != null) {
//				Logs.d(TAG, "onReceive");
//				NetworkInfo networkInfo = cm
//						.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
//				if (networkInfo == null) {
//					return;
//				}
//				wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
//						.getState();
//
//				networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
//				if (networkInfo == null) {
//					return;
//				}
//				networkInfo = cm
//						.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
//				if (networkInfo == null) {
//					return;
//				}
//				mobileState = networkInfo.getState();
//				if (mobileState != null && State.CONNECTED != wifiState
//						&& State.CONNECTED == mobileState) {
//					boolean enableUseIn3G = sharedPreferences.getBoolean(
//							KEY_USE_IN_3G, false);
//					Logs.d(TAG, "onReceive 移动网络:" + enableUseIn3G);
//					if (enableUseIn3G) {
//						Toast.makeText(context, "正在使用2G/3G/4G", 1).show();
//					} else {
//						handler.obtainMessage(MSG_PAUSE_ALL).sendToTarget();
//					}
//				} else if (wifiState != null && mobileState != null
//						&& State.CONNECTED != wifiState
//						&& State.CONNECTED != mobileState) {
//					handler.obtainMessage(MSG_PAUSE_ALL).sendToTarget();
//					Logs.d(TAG, "onReceive:没网");
//				} else if (wifiState != null && State.CONNECTED == wifiState) {
//					Logs.d(TAG, "onReceive:wifi 网络");
//				}
//			}
		}
	}

	private List<DownloadInfo> downloadEntryDatas = null;
	private Map<Long, DownloadThread> downloadTaskDatas = new LinkedHashMap<Long, DownloadThread>();
	private DownloadInfo currentDownloadData;
	private long lastExecuteTime;
	private NetworkReceiver recevier;
	private SharedPreferences sharedPreferences;

	public boolean isEnable3g() {
		return sharedPreferences.getBoolean(KEY_USE_IN_3G, false);
	}

	public DownloadManager(Context context) {
		this.context = context;
		sharedPreferences = context.getSharedPreferences(
				KEY_SHAREDPREFERENCE_NAME, Context.MODE_PRIVATE);
		db = DBController.getInstance(context);
		db.initAllDownloadInfoStatus();
		downloadEntryDatas = db.queryAllNotDownloadComplete();
		registerNetworkReceiver(context);
	}

	private void registerNetworkReceiver(Context context) {
		recevier = new NetworkReceiver();
		IntentFilter filter = new IntentFilter(
				ConnectivityManager.CONNECTIVITY_ACTION);
		context.registerReceiver(recevier, filter);
	}

	protected void removeInner(DownloadInfo data) {
		if (data.getCallback() != null) {
			data.getCallback().onRemoved();
		}
	}

	public void add(DownloadInfo data) {
		if (checkIfExecutable()) {
			if (NetworkUtils.isNetworkAvailable(context)) {
				if (!NetworkUtils.isInWifi(context)) {
					if (!isEnable3g()) {
						Toast.makeText(context, "设置里已设置为2G/3G/4G下不允许下载视频", Toast.LENGTH_SHORT)
								.show();
						return;
					} else {
						NetworkUtils.showIn234NetworkTypeToast1(context);
					}
				}
				NetworkUtils.showIn234NetworkTypeToast(context);
				onStartNotify(data);
				if (getDownloadingSize() >= Const.MAX_DOWNLOAD_TASK_SIZE) {
					data.setStatus(DownloadStatus.WAITING);
					db.newOrUpdate(data);
					addDownload(data);
					onWaitNotify(data);
				} else {
					addDownload(data);
					//					startGetFileSize(data);
					startDownload(data);
				}
			}
		}
	}

	public void pause(DownloadInfo data) {
		if (checkIfExecutable()) {
			startPause(data);
		}
	}

	public void pause(DownloadInfo data, boolean isForceExecute) {
		if (isForceExecute) {
			startPause(data);
		} else {
			if (checkIfExecutable()) {
				startPause(data);
			}
		}
	}

	private void startPause(DownloadInfo data) {
		data.setStatus(DownloadStatus.PAUSE);
		onNotify(data);
		DownloadThread downloadTask = getDownloadTask(data.getId());
		Logs.d(TAG, "pause:" + data.getName() + ":" + (downloadTask == null));
		if (downloadTask != null) {
			downloadTask.pause();
			removeDownloadTask(data.getId());
		}
		onNext(data);
	}

	public List<DownloadInfo> getDownloadingInfo() {
		return downloadEntryDatas;
	}

	public List<DownloadInfo> getDownloadInfo() {
		return db.queryAllDownloadComplete();
	}

	private synchronized DownloadThread removeDownloadTask(long id) {
		synchronized (DownloadManager.class) {
			DownloadThread downloadThread = downloadTaskDatas.get(id);
			if (downloadThread != null) {
				downloadThread.pause();
			}
			return downloadTaskDatas.remove(id);
		}
	}

	private void onNotify(DownloadInfo data) {
		if (data.getCallback() != null) {
			data.getCallback().onCancelled();
		}
	}

	private DownloadThread getDownloadTask(long id) {
		return downloadTaskDatas.get(id);
	}

	private boolean checkIfExecutable() {
		if (System.currentTimeMillis() - lastExecuteTime > MIN_EXECUTE_INTERVAL) {
			lastExecuteTime = System.currentTimeMillis();
			return true;
		}
		return false;
		//		return true;
	}

	public void resume(DownloadInfo data) {
		Logs.d(TAG, "resume");
		if (checkIfExecutable()) {
			resumeInner(data);
		}
	}

	private void resumeInner(DownloadInfo data) {
		Logs.d(TAG, "resume run");
		if (NetworkUtils.isNetworkAvailable(context)) {
			if (!NetworkUtils.isInWifi(context)) {
				if (!isEnable3g()) {
					Toast.makeText(context, "设置里已设置为2G/3G/4G下不允许下载视频", Toast.LENGTH_SHORT)
							.show();
					return;
				} else {
					NetworkUtils.showIn234NetworkTypeToast1(context);
				}
			}
			onStartNotify(data);
			Logs.d(TAG, "resume size:" + getDownloadingSize());
			removeDownloadTask(data.getId());
			if (getDownloadingSize() >= Const.MAX_DOWNLOAD_TASK_SIZE) {
				data.setStatus(DownloadStatus.WAITING);
				db.newOrUpdate(data);
				onWaitNotify(data);
			} else {
				//					currentDownloadData = data;
				//					new RefreshVideoData().execute((Void) null);
				startDownload(data);
			}
		}
	}

//	class RefreshVideoData extends AsyncTask<Void, Void, String> {
//
//		@Override
//		protected String doInBackground(Void... params) {
//			HaixueWebDataManager haixueWebDataManager = new HaixueWebDataManager(
//					context, -1);
//			VideoData videoById = haixueWebDataManager
//					.getVideoById(currentDownloadData.getVid());
//			if (videoById != null && videoById.getVideoUrl() != null) {
//				return videoById.getVideoUrl();
//			}
//			return null;
//		}
//
//		@Override
//		protected void onPostExecute(String result) {
//			if (result != null) {
//				currentDownloadData.setUrl(result);
//				startDownload(currentDownloadData);
//			}
//			super.onPostExecute(result);
//		}
//	}

	private void addDownload(DownloadInfo data) {
		downloadEntryDatas.add(data);
	}

	private void onWaitNotify(DownloadInfo data) {
		if (data.getCallback() != null) {
			data.getCallback().onWaiting();
		}
	}

	private void onStartNotify(DownloadInfo data) {
		if (data.getCallback() != null) {
			data.setStatus(DownloadStatus.START);
			data.getCallback().onStart();
		}
	}

	//	private void startGetFileSize(DownloadInfo data) {
	//		currentDownloadData = data;
	//		new GetFileLengthTask().execute(data.getUrl());
	//	}

	//	class GetFileLengthTask extends AsyncTask<String, Void, Long> {
	//
	//		@Override
	//		protected Long doInBackground(String... arg0) {
	//			return getFilelength(arg0);
	//		}
	//
	//		@Override
	//		protected void onPostExecute(Long result) {
	//			currentDownloadData.setSize(result);
	//			startDownload(currentDownloadData);
	//		}
	//
	//	}

	private Long getFilelength(String... arg0) {
		try {
			BasicHttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters,
					Const.CONNECT_TIMEOUT);
			HttpConnectionParams.setSoTimeout(httpParameters,
					Const.READ_TIMEOUT);
			HttpGet getMethod = new HttpGet(arg0[0]);
			HttpClient httpClient = new DefaultHttpClient();
			HttpResponse response = httpClient.execute(getMethod);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				long contentLength = response.getEntity().getContentLength();
				return contentLength;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return (long) -1;
	}

	public void startDownload(DownloadInfo data) {
		DownloadThread downloadThread = new DownloadThread(data, this, db);
		downloadThread.start();
		downloadTaskDatas.put(data.getId(), downloadThread);
	}

	public synchronized int getDownloadingSize() {
		synchronized (DownloadManager.class) {
			return downloadTaskDatas.size();
		}
	}

	public int getDownloadingEntrySize() {
		return downloadEntryDatas.size();
	}

	public int getDownloadedSize() {
		return db.queryDownloadedSize();
	}

	public DownloadInfo getDownloadInfoBy(long id) {
		int size = downloadEntryDatas.size();
		for (int i = 0; i < size; i++) {
			if (downloadEntryDatas.get(i).getId() == id) {
				return downloadEntryDatas.get(i);
			}
		}
		return null;
	}

	@Override
	public void onProgress(DownloadInfo data) {
		handler.sendMessage(handler.obtainMessage(MSG_UPDATE_PROGRESS, data));
	}

	/**鏍规嵁id鑾峰彇涓嬭浇 淇℃伅锛屽厛鍘绘暟鎹簱鏌ヨ宸插畬鎴愯涓猴紝濡傛灉涓簄ull锛屽啀鍘讳笅杞介泦鍚堟煡璇�
	 * @param id
	 * @return
	 */
	public DownloadInfo getDownload(long id, DownloadManager downloadManager) {
		DownloadInfo downloadInfo = db.queryDownloadInfo(id);
		if (downloadInfo == null) {
			downloadInfo = downloadManager.getDownloadInfoBy(id);
			return downloadInfo;
		}
		return downloadInfo;
	}

	/**
	 * @param data
	 */
	public void remove(DownloadInfo data) {
		if (data != null) {
			downloadEntryDatas.remove(data);
			handler.obtainMessage(MSG_NEXT_DOWNLOAD_REMOVE_DATA, data)
					.sendToTarget();
			db.deleteDownloadInfo(data.getId());
			File file = new File(data.getPath());
			if (file.exists()) {
				file.delete();
			}
		}
	}

	public void removeAll(List<DownloadInfo> datas) {
		DownloadInfo lastDownloadInfo = null;
		for (int i = 0; i < datas.size(); i++) {
			delete(datas.get(i));
			if (i == datas.size() - 1) {
				lastDownloadInfo = datas.get(i);
			}
			downloadEntryDatas.remove(datas.get(i));
			db.deleteDownloadInfo(datas.get(i).getId());
			File file = new File(datas.get(i).getPath());
			if (file.exists()) {
				file.delete();
			}
		}
		handler.obtainMessage(MSG_NEXT_DOWNLOAD_REMOVE_DATA, lastDownloadInfo)
				.sendToTarget();
	}

	private void delete(DownloadInfo data) {
		data.setStatus(DownloadStatus.DELETE);
		onNotify(data);
		DownloadThread downloadTask = getDownloadTask(data.getId());
		Logs.d(TAG, "pause:" + data.getName() + ":" + (downloadTask == null));
		if (downloadTask != null) {
			downloadTask.pause();
			removeDownloadTask(data.getId());
		}
		onNext(data);
	}

	@Override
	public void onNext(DownloadInfo data) {
		removeDownloadTask(data.getId());
//		if (data.getStatus() == DownloadStatus.DONE) {
//			removeDownload(data);
//			encodeVideo(data);
//		}
		for (DownloadInfo item : downloadEntryDatas) {
			if (item.getStatus() ==DownloadStatus.WAITING) {
				handler.sendMessage(handler.obtainMessage(
						MSG_NEXT_DOWNLOAD_TASK, item));
				//				add(item);
				break;
			}
		}
	}

//	private void encodeVideo(final DownloadInfo data) {
//		new Thread() {
//			public void run() {
//				VideoUtils.encodeVideo(data.getPath());
//			};
//		}.start();
//	}

	private void removeDownload(DownloadInfo data) {
		downloadEntryDatas.remove(data);
		handler.obtainMessage(MSG_NEXT_DOWNLOAD_REMOVE_DATA, data)
				.sendToTarget();
	}

	public void pauseAll() {
		for (DownloadInfo item : downloadEntryDatas) {
			if (item.getStatus() == DownloadStatus.WAITING
					|| item.getStatus() == DownloadStatus.LOADING) {
				pause(item, true);
			}
		}
	}

	public void destory() {
		Intent downloadSvr = new Intent(context, DownloadService.class);
		context.stopService(downloadSvr);
		DownloadService.DOWNLOAD_MANAGER = null;
		DBController.instance = null;
	}

	public void onDestory() {
		Logs.d(TAG, "download manager onDestory");
		if (recevier != null) {
			context.unregisterReceiver(recevier);
			recevier = null;
			Logs.d(TAG, "download manager onDestory unregisterReceiver");

		}
	}
}
